﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HidesaburoDotNET.Core.AI;
using HidesaburoDotNET.Core;
using System.Windows.Forms;

namespace HidesaburoMohjang
{
    /// <summary>
    /// 人間の操作者を表すAI
    /// 
    /// </summary>
    public class Operator : AbstractAI
    {
        Form form;
        /// <summary>
        /// 牌を引き、捨てる牌を選ぶ時に呼び出され、捨てる牌を選択します
        /// </summary>
        public event OperatorEvent<Hai> DiscardEvent;
        /// <summary>
        /// 上がれる状態になった時に呼び出され、上がるかどうかを選択します
        /// </summary>
        public event OperatorEvent<Boolean> DecideFinishEvent;
        /// <summary>
        /// ほかのプレイヤーが牌を捨てたとき、鳴くことができる場合に呼び出されます。
        /// 行うアクションを選択します。
        /// </summary>
        public event ActionEvent CheckActionEvent;

        public Operator(Form form) { this.form = form; }


        public override void OnPlayerSet(Player player)
        {

        }

        public override bool DecideFinish(CompleteEventArgs args)
        {
            return false;
        }

        public override Hai SelectDiscard()
        {

            if (DiscardEvent != null)
            {
                OperatorEventArgs<Hai> args = new OperatorEventArgs<Hai>();
                DiscardEvent(this, args);

                while (form.Created && args.Flag == null)
                {
                    Application.DoEvents();
                }
                return args.WaitValue;
            }
            

            return player.Tehai.LastDrew;
        }
        


        public override NakiAction CheckAction(Player sender, Hai discard)
        {
            if ( CheckActionEvent != null)
            {
                ActionEventArgs args =
                    new ActionEventArgs(
                        discard,
                        GetAvailableActions(discard)
                        );
                if (args.AvailableActions.Count > 0)
                {
                    CheckActionEvent(this, args);

                    while (form.Created && args.Flag == null)
                    {
                        Application.DoEvents();
                    }
                    return args.WaitValue;
                }

            }

            return NakiAction.None;
        }

        private List<NakiAction> GetAvailableActions(Hai discard)
        {
            Tehai t = player.Tehai;
            List<NakiAction> actions = new List<NakiAction>();
            if (t.CanRon(discard))
            {
                actions.Add(NakiAction.Ron);
            }
            if (t.CanKan(discard))
            {
                actions.Add(NakiAction.Kan);
            }
            if (t.CanPon(discard))
            {
                actions.Add(NakiAction.Pon);
            }
            actions.AddRange(t.CanAnyChi(discard));

            return actions;
        }

        public override object Clone()
        {
            return this;
        }
    }
    public delegate void OperatorEvent<T>(Operator sender, OperatorEventArgs<T> args);
    public delegate void ActionEvent(Operator sender, ActionEventArgs args);
    /// <summary>
    /// 操作者に関するイベントのベースとなるクラス
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class OperatorEventArgs<T> : EventArgs
    {
        object flag = null;
        /// <summary>
        /// メソッドのブロックを制御するフラッグ
        /// このFlagがNullで無くなった時に、ゲーム進行のブロックが解除されます。
        /// </summary>
        public object Flag
        {
            get { return flag; }
            set { flag = value; }
        }
        T waitValue;

        /// <summary>
        /// ゲームシステム側が要求する値。
        /// この値が代入されたときに、ゲーム進行のブロックが解除されます。
        /// </summary>
        public T WaitValue
        {
            get { return waitValue; }
            set {
                waitValue = value;
                flag = new object();
            }
        }

        public OperatorEventArgs()
        {

        }


    }
    /// <summary>
    /// アクションイベント。
    /// </summary>
    public class ActionEventArgs : OperatorEventArgs<NakiAction>
    {
        Hai discard;

        /// <summary>
        /// 捨てられた牌
        /// </summary>
        public Hai Discard
        {
            get { return discard; }
        }

        List<NakiAction> availableActions;

        /// <summary>
        /// 行うことが可能なアクションのリスト
        /// </summary>
        public List<NakiAction> AvailableActions
        {
            get { return availableActions; }
        }
        public ActionEventArgs(Hai hai, List<NakiAction> availableActions)
        {
            this.discard = hai;
            this.availableActions = availableActions;
        }
    }
}
